home *** CD-ROM | disk | FTP | other *** search
- // ------------------------ WINFIRE.C ------------------------------
- // Coded bye Jare of Iguana near Xmas of 1994
- // Comments to a880104@zipi.fi.upm.es
- // My original ASM routine was 200 lines of plain ASM, this Windows
- // version goes up to near 500 lines!!
- // You can use this for anything you like, but you must credit me.
-
- #include <windows.h>
- #include <wing.h>
- #include <stdlib.h>
- #include <string.h>
-
- // Fire array size.
- #define FIREW 128
- #define FIREH 96
- // Nice size for the window. Frame will take some bits apart, however.
- #define WINDOWW FIREW*4
- #define WINDOWH FIREH*4
-
- // Handy msg structure.
- typedef struct {
- HWND hwnd;
- UINT msg;
- WPARAM wParam;
- LPARAM lParam;
- } tMSG, *pMSG;
-
- // Low Level data types.
- typedef unsigned char byte;
- typedef unsigned short word;
- typedef unsigned long dword;
-
- typedef byte * Pbyte;
- typedef word * Pword;
- typedef dword * Pdword;
-
- typedef byte FAR * LPbyte;
- typedef word FAR * LPword;
- typedef dword FAR * LPdword;
-
- // ===============================================================
- // WinG DC handling functions.
-
- // The stock default bitmap of a WinGDC.
- static HBITMAP hBitmapMonochrome = 0;
-
- // Creates a top-down WinGDC with the specified rgb palette.
- // Returns the HDC and stores the bitmap pointer in ppSurfaceBits,
- // if not passed a NULL parameter.
-
- static HDC MakeWinGDC(RGBQUAD rgb[256], LPbyte *ppSurfaceBits) {
- HDC hWinGDC;
- HBITMAP hBitmapNew;
- int i;
- struct {
- BITMAPINFOHEADER Header;
- RGBQUAD ColorTable[256];
- } Info;
-
- // Force top-down 8-bit bitmap of size FIREW*FIREH.
- Info.Header.biSize = sizeof(Info.Header);
- Info.Header.biPlanes = 1;
- Info.Header.biBitCount = 8;
- Info.Header.biCompression = BI_RGB;
- Info.Header.biSizeImage = 0;
- Info.Header.biClrUsed = 0;
- Info.Header.biClrImportant = 0;
- Info.Header.biWidth = FIREW;
- Info.Header.biHeight = -FIREH; // Minus for top-down.
-
- for (i = 0; i < 256; i++)
- Info.ColorTable[i] = rgb[i];
-
- // Create a WinGDC and Bitmap, then select away DC's default
- // monochrome bitmap.
- hWinGDC = WinGCreateDC();
- if (hWinGDC) {
- hBitmapNew = WinGCreateBitmap(hWinGDC,
- (LPBITMAPINFO)&Info,
- ppSurfaceBits);
- if (hBitmapNew) {
- hBitmapMonochrome = (HBITMAP)SelectObject(hWinGDC,
- hBitmapNew);
- } else {
- DeleteDC(hWinGDC);
- hWinGDC = 0;
- }
- }
- return hWinGDC;
- }
-
- // Finishes the WinGDC. Pretty straightforward.
-
- static void EndWinGDC(HDC hWinGDC) {
- HBITMAP hBitmapOld;
-
- if (hWinGDC && hBitmapMonochrome) {
- // Select the stock 1x1 monochrome bitmap back in
- hBitmapOld = (HBITMAP)SelectObject(hWinGDC,
- hBitmapMonochrome);
- hBitmapMonochrome = 0;
- DeleteObject(hBitmapOld);
- DeleteDC(hWinGDC);
- }
- }
-
- // Creates a palette from the specified colors, but requires
- // using the system colors. Updates 'rgb' to enable the use of an
- // identity palette i.e. on exit, rgb contains the effective
- // palette, that can in turn be used for creating the WinGDC.
-
- static HPALETTE CreateIdentityPalette(RGBQUAD aRGB[256], int nColors) {
- int i;
- static struct {
- WORD Version;
- WORD NumberOfEntries;
- PALETTEENTRY aEntries[256];
- } pal = {
- 0x300,
- 256
- };
- HDC hdc;
-
- // For SYSPAL_STATIC, get the twenty static colors into
- // the array, then fill in the empty spaces with the
- // given color table
-
- hdc = GetDC(NULL);
- // Get the static colors
- GetSystemPaletteEntries(hdc, 0, 10, pal.aEntries);
- GetSystemPaletteEntries(hdc, 246, 10, pal.aEntries + 246);
-
- // Set the peFlags of the lower static colors to zero.
- // And copy the static colors to the user palette so
- // the caller knows exactly which palette we created.
- for (i = 0; i < 10; i++) {
- aRGB[i].rgbRed = pal.aEntries[i].peRed;
- aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
- aRGB[i].rgbBlue = pal.aEntries[i].peBlue;
- pal.aEntries[i].peFlags = 0;
- }
-
- // Fill in the entries from the given color table
- for (; i < nColors+10; i++) {
- pal.aEntries[i].peRed = aRGB[i].rgbRed;
- pal.aEntries[i].peGreen = aRGB[i].rgbGreen;
- pal.aEntries[i].peBlue = aRGB[i].rgbBlue;
- pal.aEntries[i].peFlags = PC_RESERVED;
- }
-
- // Mark any empty entries as PC_RESERVED
- for (; i < 246; i++) {
- aRGB[i].rgbRed = pal.aEntries[i].peRed;
- aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
- aRGB[i].rgbBlue = pal.aEntries[i].peBlue;
- pal.aEntries[i].peFlags = PC_RESERVED;
- }
-
- // Set the peFlags of the upper static colors to zero, and
- // copy static colors.
- for (; i < 256; i++) {
- aRGB[i].rgbRed = pal.aEntries[i].peRed;
- aRGB[i].rgbGreen = pal.aEntries[i].peGreen;
- aRGB[i].rgbBlue = pal.aEntries[i].peBlue;
- pal.aEntries[i].peFlags = 0;
- }
-
- ReleaseDC(NULL, hdc);
-
- // Create the palette
- return CreatePalette((LOGPALETTE *)&pal);
- }
-
- // ===============================================================
- // Fire algorithm. Pure C, ASM will do it much faster.
-
- static void DoFire(Pbyte to, Pbyte from) {
- int i, j;
-
- from += FIREW;
- to += 0;
-
- // All lines but the first and last. The first will disappear,
- // and the last must be taken with care for the limits of the
- // array.
- for (i = 1; i < FIREH-1; i++) {
- // Leftmost pixel.
- *to++ = (byte)(( (word)from[-1] + (word)from[1]
- + (word)from[-(int)FIREW] + (word)from[FIREW]) >> 2);
- from++;
- // Middle pixels.
- for (j = 1; j < FIREW-1; j++) {
- *to++ = (byte)(( (word)from[-1] + (word)from[1]
- + (word)from[-(int)FIREW-1] + (word)from[-(int)FIREW+1]
- + (word)from[+(int)FIREW-1] + (word)from[+(int)FIREW+1]
- + (word)from[-(int)FIREW] + (word)from[FIREW]
- ) >> 3);
- from++;
- }
- // Rightmost pixel.
- *to++ = (byte)(( (word)from[-1] + (word)from[1]
- + (word)from[-(int)FIREW] + (word)from[FIREW]) >> 2);
- from++;
- }
- // Bottom line.
- for (j = 0; j < FIREW-1; j++) {
- *to++ = (byte)(( (word)from[-1] + (word)from[1]
- + (word)from[-(int)FIREW] + (word)from[0]) >> 2);
- from++;
- }
- // Rightmost pixel of bottom line.
- *to = (byte)(((word)from[-1] + (word)from[-(int)FIREW]) >> 1);
- }
-
- // ===============================================================
- // Fire Window message handlers.
-
- // Global vars.
- static HINSTANCE AppInstance; // ditto.
-
- static HDC ScreenHDC; // WinGDC created.
- static LPbyte Screen; // Pointer to the surface bitmap.
- static UINT Timer; // Timer identifier.
- static RGBQUAD rgb[256]; // Palette used.
- static HPALETTE Palette; // Handle to it.
- static int WindowState; // Minimized, maximized or normal?
- static HICON FireIcon; // Handle to icon for QueryDragIcon.
-
- // Fire buffers. FAR so the are in their own data segment.
- static byte FireBuf1[FIREW*FIREH], FireBuf2[FIREW*FIREH];
- static Pbyte Buf1 = FireBuf1, Buf2 = FireBuf2;
-
- // ---------- Message handlers.
-
- static LRESULT wmCreate(pMSG msg) {
- int i;
-
- FireIcon = LoadIcon(AppInstance, "FIREICON");
-
- // Create a smooth palette.
- memset(rgb, 0, sizeof(rgb));
- for (i = 10; i < 10+16; i++)
- rgb[i].rgbRed = (BYTE)((i-10)*16);
- for (; i < 10+48; i++) {
- rgb[i].rgbRed = 255;
- rgb[i].rgbGreen = (BYTE)((i-10-16)*8);
- }
- for (; i < 10+80; i++) {
- rgb[i].rgbRed = 255;
- rgb[i].rgbGreen = 255;
- rgb[i].rgbBlue = (BYTE)((i-10-48)*8);
- }
- for (; i < 10+236; i++) {
- rgb[i].rgbRed = 255;
- rgb[i].rgbGreen = 255;
- rgb[i].rgbBlue = 255;
- }
-
- // Clean up buffers.
- memset(FireBuf1, 0, sizeof(FireBuf1));
- memset(FireBuf2, 0, sizeof(FireBuf2));
-
- // Create stuff.
- Palette = CreateIdentityPalette(rgb, 236);
- ScreenHDC = MakeWinGDC(rgb, &Screen);
- WindowState = SC_RESTORE;
- Timer = SetTimer(msg->hwnd, 1, 1, NULL);
- return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
- }
-
- static LRESULT wmDestroy(pMSG msg) {
- KillTimer(msg->hwnd, Timer);
- EndWinGDC(ScreenHDC);
- if (Palette != 0)
- DeleteObject(Palette);
- DestroyIcon(FireIcon);
- return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
- }
-
- static LRESULT wmTimer(pMSG msg) {
- HDC hdc;
- int i;
- LPdword p;
- Pdword q;
- Pbyte s;
- RECT r;
-
- // Clean bottom line.
- memset(Buf2 + FIREW*(FIREH-1), 0, FIREW);
- // Set random hot spots and animate.
- for (i = 0; i < 20; i++) {
- int k = rand() % (FIREW-2);
- Buf2[FIREW*FIREH - k] = 235;
- }
- DoFire(Buf1, Buf2);
-
- // Copy buffer to the WinGDC bitmap, adding 10 for the colors.
- p = (LPdword)Screen;
- q = (Pdword)Buf1;
- for (i = 0; i < FIREH*FIREW/4; i++)
- *p++ = *q++ + 0x0a0a0a0a;
-
- // Swap buffers.
- s = Buf1;
- Buf1 = Buf2;
- Buf2 = s;
-
- // Dump bitmap.
- GetClientRect(msg->hwnd, &r);
- hdc = GetDC(msg->hwnd);
- SelectPalette(hdc, Palette, FALSE);
- RealizePalette(hdc);
-
- // If window is not minimized or maximized, do optimal stretch
- // by multiplying by 2^2, else stretch to whatever the size.
- // Vertical stretch can be anything, as it doesn't slow down
- // if it's not stretched by a power of two.
- if (WindowState == SC_MINIMIZE || WindowState == SC_MAXIMIZE)
- WinGStretchBlt(hdc, 0, 0, r.right-r.left, r.bottom-r.top,
- ScreenHDC, 0, 0, FIREW, FIREH);
- else
- WinGStretchBlt(hdc, 0, 0, WINDOWW, r.bottom-r.top,
- ScreenHDC, 0, 0, FIREW, FIREH);
- ReleaseDC(msg->hwnd, hdc);
-
- return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
- }
-
- static LRESULT wmQueryNewPalette(pMSG msg) {
- HDC hdc;
- LRESULT f;
-
- hdc = GetDC(msg->hwnd);
- if (Palette)
- SelectPalette(hdc, Palette, FALSE);
- f = RealizePalette(hdc);
- ReleaseDC(msg->hwnd, hdc);
- return f;
- }
-
- static LRESULT wmSysCommand(pMSG msg) {
- if (msg->wParam == SC_MINIMIZE ||
- msg->wParam == SC_MAXIMIZE ||
- msg->wParam == SC_RESTORE)
- WindowState = msg->wParam;
- return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
- }
-
- static LRESULT wmWindowPosChanging(pMSG msg) {
- LPWINDOWPOS lpwp;
- RECT rw, rc;
- int x, w;
-
- // If window is not maximized or minimized, align its client
- // area to a four-pixel boundary for optimal performance.
- if (WindowState == SC_RESTORE) {
- lpwp = (LPWINDOWPOS)msg->lParam;
- GetWindowRect(msg->hwnd, &rw);
- GetClientRect(msg->hwnd, &rc);
- w = rw.right - rw.left - (rc.right - rc.left); // Width of frame.
- x = lpwp->x + w;
- lpwp->x = (x & ~3) - w; // Align it.
- if (lpwp->cx - w > WINDOWW)
- lpwp->cx = w + WINDOWW;
- }
- return DefWindowProc(msg->hwnd, msg->msg, msg->wParam, msg->lParam);
- }
-
-
- // Window procedure.
- LRESULT CALLBACK FireWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- tMSG m;
-
- m.hwnd = hwnd;
- m.msg = msg;
- m.wParam = wParam;
- m.lParam = lParam;
-
- switch (msg) {
- case WM_CREATE: return wmCreate(&m);
- case WM_DESTROY: return wmDestroy(&m);
- case WM_QUERYDRAGICON:
- if (FireIcon != (HICON)NULL)
- return FireIcon;
- break;
-
- case WM_TIMER: return wmTimer(&m);
-
- case WM_PALETTECHANGED:
- if ((HWND)wParam != hwnd) // If we changed the palette.
- return wmQueryNewPalette(&m);
- break;
- case WM_QUERYNEWPALETTE: return wmQueryNewPalette(&m);
-
- case WM_WINDOWPOSCHANGING: return wmWindowPosChanging(&m);
- case WM_SYSCOMMAND: return wmSysCommand(&m);
-
- case WM_CLOSE:
- PostQuitMessage(0);
- break;
- }
-
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
-
- // ===============================================================
- // Main entry point.
-
- int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {
- static char ClassName[] = "WinFire";
- static char AppName[] = "WinFire";
- int w, h;
- MSG msg;
- HWND hwnd;
-
- if (hPrev == 0) {
- WNDCLASS c;
-
- c.hCursor = LoadCursor(NULL, IDC_WAIT);
- c.hIcon = NULL;
- c.lpszMenuName = NULL;
- c.lpszClassName = "WinFire";
- c.hbrBackground = NULL;
- c.hInstance = hInst;
- c.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
- c.lpfnWndProc = (WNDPROC)FireWndProc;
- c.cbWndExtra = 0;
- c.cbClsExtra = 0;
- if (!RegisterClass(&c))
- return 1;
- }
-
- AppInstance = hInst;
- w = GetSystemMetrics(SM_CXSCREEN);
- h = GetSystemMetrics(SM_CYSCREEN);
-
- hwnd = CreateWindow (ClassName, // Class name
- AppName, // Caption
- WS_OVERLAPPEDWINDOW, // Style bits
- (w-WINDOWW)/2, (h-WINDOWH)/2, // Position
- WINDOWW, WINDOWH, // Size
- (HWND)NULL, // Parent window (no parent)
- (HMENU)NULL, // no menu
- hInst, // handle to window instance
- (LPSTR)NULL // no params to pass on
- );
- if (hwnd == (HWND)NULL)
- return 1;
- ShowWindow(hwnd, sw);
-
- while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return 0;
- }
-
- // ------------------------ WINFIRE.C ------------------------------
-
-